home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #42 (Mar 89) / Window Source / Window2.p < prev   
Text File  |  1989-04-04  |  46KB  |  1,736 lines

  1. (*
  2.  
  3. © 1988, Apple Computer, Inc.
  4. All rights reserved.
  5.  
  6. Window2.p:        A HyperCard XCMD in MPW Pascal 2.0.2 by Joe Zuffoletto
  7.                 Version 1.0, 29 June 1988
  8.  
  9. Form:            window title,top,left,bottom,right
  10.  
  11. Example:        window "My Window",50,100,300,400
  12.  
  13. Notes:            Window puts up a standard document window with scroll bars.
  14.                 The window can be dragged, resized, zoomed, and closed.
  15.                 
  16.                 Command-W is supported for closing the window. Command-spacebar
  17.                 toggles the menubar on and off, as in HyperCard.  If you
  18.                 try to draw the window's title bar off the screen or under
  19.                 the menubar, Window will abort with an error message. Error
  20.                 messages can be examined by looking at HyperCard's global
  21.                 variable "the result" after calling Window.
  22.                 
  23.                 Window is MultiFinder friendly and works with all 
  24.                 versions of HyperCard through 1.2.1. It supports multiple
  25.                 displays on the Mac II as well. 
  26.                 
  27.                 Window takes a snapshot of the HyperCard card window and
  28.                 displays it like a MacPaint document. You can scroll up
  29.                 and down, etc. This is just for demonstration and amusement.
  30.                 You must supply your own code for displaying whatever you
  31.                 want to display in the window.
  32.                 
  33. -----------------------------------------------------------------------------
  34.  
  35. To compile and link this file using MPW Pascal 2.0.2, select the following lines
  36. and press ENTER:
  37.  
  38. Pascal Window2.p
  39. link    -o "Hard Disk":HyperCard:"HyperCard Stacks":Home ∂
  40.        -rt XCMD=2000 -sn Main=Window ∂
  41.         Window2.p.o {MPW}Libraries:Interface.o ∂
  42.         {MPW}PLibraries:PasLib.o ∂
  43.         -m ENTRYPOINT
  44.         
  45. Use other link files as necessary.
  46.  
  47. The above link directives install the XCMD resource into the Home stack. You
  48. can substitute the name of any stack you want; be sure to provide the
  49. correct pathname. Also, make sure the target stack already has a resource
  50. fork or it won't work. You can create an empty resource fork in a stack
  51. with ResEdit.
  52.  
  53. -----------------------------------------------------------------------------
  54.  
  55. *)
  56.  
  57. {$R-}
  58.  
  59. {$S Window}
  60.  
  61. UNIT DummyUnit;
  62.  
  63. INTERFACE
  64.  
  65. USES MemTypes,QuickDraw,OSIntf,ToolIntf,PasLibIntf,HyperXCmd;
  66.  
  67. PROCEDURE EntryPoint(paramPtr:XCmdPtr);
  68.  
  69. IMPLEMENTATION
  70.  
  71. TYPE    Str31    =    String[31];
  72.  
  73.         OffScrHandle    =    ^OffScrRecPtr;                {Attach to refCon of a window}
  74.         OffScrRecPtr    =    ^OffScrRecord;
  75.         OffScrRecord    =    RECORD
  76.                                 gPort:        GrafPtr;    {Offscreen GrafPort}
  77.                                 docWidth:    INTEGER;    {Document's width in pixels}
  78.                                 docHeight:    INTEGER;    {Document's height in pixels}
  79.                                 blitRect:    Rect;        {'Window' onto O.G.}
  80.                                 blitWidth:    INTEGER;    {Current width of O.G. 'window'}
  81.                                 blitHeight:    INTEGER;    {Current height of O.G. 'window'}
  82.                                 dhGraf:        LONGINT;    {Pixels scrolled horizontally}
  83.                                 dvGraf:        LONGINT;    {Pixels scrolled vertically}
  84.                             END;
  85.  
  86.         ScrollHandle    =    ^ScrollPtr;                    {Attach to refCon of a scroll bar}
  87.         ScrollPtr        =    ^ScrollRecord;
  88.         ScrollRecord    =    RECORD
  89.                                 heldDown:    INTEGER;    {See procedure MyScroll}
  90.                                 goFast:        BOOLEAN;
  91.                             END;
  92.  
  93. PROCEDURE Window(paramPtr:XCmdPtr);FORWARD;
  94.  
  95. PROCEDURE EntryPoint(paramPtr:XCmdPtr);
  96. BEGIN
  97.     Window(paramPtr);
  98. END;
  99.  
  100.  
  101. FUNCTION Min(int1,int2:INTEGER): INTEGER;
  102.  
  103. {Return the smaller of two integers.}
  104.  
  105. BEGIN
  106.     IF (int1 <= int2) THEN
  107.         Min := int1
  108.     ELSE
  109.         Min := Int2;
  110. END; {Min}
  111.  
  112.     
  113. PROCEDURE InitBlit(theWindow:WindowPtr);
  114.  
  115. {Initialize the blit rectangle so it is in the upper left
  116.  corner of the offscreen bitmap and so it is the same size
  117.  as the target window onscreen.}
  118.  
  119. VAR
  120.     myOffScrHandle:    OffScrHandle;
  121.  
  122. BEGIN
  123.     myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  124.     MoveHHi(Handle(myOffScrHandle));
  125.     HLock(Handle(myOffScrHandle));
  126.     WITH myOffScrHandle^^ DO
  127.     BEGIN
  128.         dhGraf := 0;
  129.         dvGraf := 0;
  130.         
  131.         {Make sure blit rectangle doesn't hang off edges of offscreen bitmap, just
  132.          in case window is larger.}
  133.         
  134.         blitWidth := Min((theWindow^.portRect.right - 15 - theWindow^.portRect.left),docWidth);
  135.         blitHeight := Min((theWindow^.portRect.bottom - 15 - theWindow^.portRect.top),docHeight);
  136.         SetRect(blitRect,gPort^.portBits.bounds.left,
  137.                          gPort^.portBits.bounds.top,
  138.                          gPort^.portBits.bounds.left + blitWidth,
  139.                          gPort^.portBits.bounds.top + blitHeight);
  140.     END;
  141.     HUnlock(Handle(myOffScrHandle));
  142. END; {InitBlit}
  143.  
  144.  
  145. PROCEDURE InvalContents(theWindow:WindowPtr;theOldSize:Rect);
  146.  
  147. {Perform "intelligent" window updating; i.e., if the window is
  148.  grown, invalidate for the update event only the part that wasn't 
  149.  visible before.}
  150.  
  151. VAR
  152.     myOffScrHandle:                OffScrHandle;
  153.     myWindowRect,windowRect:    Rect;
  154.     tallRect,wideRect:            Rect;
  155.     hWhiteSpace,vWhiteSpace:    INTEGER;
  156.     hBlitOffset,vBlitOffset:    INTEGER;
  157.     myDocWidth,myDocHeight:        INTEGER;
  158.     newDhGraf,newDvGraf:        LONGINT;
  159.     tempDH,tempDV:                LONGINT;
  160.     
  161. BEGIN
  162.     hBlitOffset := 0;
  163.     vBlitOffset := 0;
  164.     myWindowRect := theWindow^.portRect;
  165.     myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  166.     MoveHHi(Handle(myOffScrHandle));
  167.     HLock(Handle(myOffScrHandle));
  168.     WITH myOffScrHandle^^ DO
  169.     BEGIN
  170.         tempDH := dhGraf;
  171.         tempDV := dvGraf;
  172.         myDocWidth := docWidth;
  173.         myDocHeight := docHeight;
  174.     END;
  175.     
  176.     {If we have scrolled to the bottom and/or right edges of the document and then
  177.      grow the window, the document will "follow" the window so we don't just expose
  178.      a lot of white space. The same thing will happen if we zoom the window to a
  179.      larger size. In either case, we need to invalidate the entire content region.}
  180.      
  181.      {Is any white space being exposed in the horizontal direction?}
  182.     
  183.     hWhiteSpace := (myWindowRect.right - myWindowRect.left - 15) - (myDocWidth - tempDH);
  184.     IF (hWhiteSpace > 0) THEN
  185.     BEGIN
  186.     
  187.         {If so, how much?}
  188.         
  189.         newDhGraf := tempDH - hWhiteSpace;
  190.         
  191.         {Move the document that distance, but not beyond the point where its
  192.          left edge is flush with the left edge of the window.}
  193.          
  194.         IF newDhGraf < 0 THEN
  195.             newDhGraf := 0;
  196.             
  197.         {Adjust blit rectangle accordingly.}
  198.         
  199.         hBlitOffset := INTEGER(tempDH - newDhGraf);
  200.         tempDH := newDhGraf;
  201.     END; {IF hWhiteSpace}
  202.     
  203.     {Repeat for vertical direction.}
  204.             
  205.     vWhiteSpace := (myWindowRect.bottom - myWindowRect.top - 15) - (myDocHeight - tempDV);
  206.     IF (vWhiteSpace > 0) THEN
  207.     BEGIN
  208.         newDvGraf := tempDV - vWhiteSpace;
  209.         IF newDvGraf < 0 THEN
  210.             newDvGraf := 0;
  211.         vBlitOffset := INTEGER(tempDV - newDvGraf);
  212.         tempDV := newDvGraf;
  213.     END; {IF vWhiteSpace}
  214.     
  215.     {Save what we've learned to the data structure.}
  216.     
  217.     WITH myOffScrHandle^^ DO
  218.     BEGIN
  219.         dhGraf := tempDH;
  220.         dvGraf := tempDV;
  221.         blitWidth := Min((myWindowRect.right - myWindowRect.left - 15),
  222.                         (myDocWidth - dhGraf));
  223.         blitHeight := Min((myWindowRect.bottom - myWindowRect.top - 15),
  224.                          (myDocHeight - dvGraf));
  225.         SetRect(blitRect,blitRect.left - hBlitOffset,
  226.                           blitRect.top - vBlitOffset,
  227.                           blitRect.left + blitWidth - hBlitOffset,
  228.                           blitRect.top + blitHeight - vBlitOffset);
  229.         blitWidth := blitRect.right - blitRect.left;
  230.         blitHeight := blitRect.bottom - blitRect.top;
  231.     END;
  232.     HUnlock(Handle(myOffScrHandle));
  233.                      
  234.     {If the document has followed the window, invalidate entire content
  235.      region.}
  236.       
  237.     IF ((hBlitOffset <> 0) OR (vBlitOffset <> 0)) THEN
  238.     BEGIN
  239.         EraseRect(theWindow^.portRect);
  240.         InvalRect(theWindow^.portRect);
  241.     END
  242.     ELSE
  243.     
  244.     {Otherwise invalidate only the new white space.}
  245.     
  246.     BEGIN
  247.         SetRect(tallRect,theOldSize.right,
  248.                          theWindow^.portRect.top,
  249.                          theWindow^.portRect.right,
  250.                          theWindow^.portRect.bottom);
  251.         SetRect(wideRect,theWindow^.portRect.left,
  252.                          theOldSize.bottom,
  253.                          theOldSize.right,
  254.                          theWindow^.portRect.bottom);
  255.         EraseRect(tallRect);
  256.         EraseRect(wideRect);
  257.         InvalRect(tallRect);
  258.         InvalRect(wideRect);
  259.     END; {IF hBlitOffset}
  260. END; {InvalContents}
  261.     
  262.     
  263. PROCEDURE DrawContents(theWindow:WindowPtr);
  264.  
  265. {Blasts contents of updated blit rectangle to screen.}
  266.  
  267. VAR
  268.     myWindowRect,windowRect:    Rect;
  269.     myOffScrHandle:                OffScrHandle;
  270.  
  271. BEGIN
  272.     myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  273.     myWindowRect := theWindow^.portRect;
  274.     MoveHHi(Handle(myOffScrHandle));
  275.     HLock(Handle(myOffScrHandle));
  276.     SetRect(windowRect,myWindowRect.left,
  277.                        myWindowRect.top,
  278.                        myWindowRect.left + myOffScrHandle^^.blitWidth,
  279.                        myWindowRect.top + myOffScrHandle^^.blitHeight);
  280.     ClipRect(windowRect);
  281.     CopyBits(myOffScrHandle^^.gPort^.portBits,theWindow^.portBits,
  282.              myOffScrHandle^^.blitRect,windowRect,
  283.              srcCopy,NIL);
  284.     HUnlock(Handle(myOffScrHandle));
  285. END; {DrawContents}
  286.     
  287.     
  288. PROCEDURE ScrollContents(theWindow:WindowPtr;dh,dv:INTEGER);
  289.  
  290. VAR
  291.     myOffScrHandle:                OffScrHandle;
  292.     leftSpace,topSpace:            INTEGER;
  293.     rightSpace,bottomSpace:        INTEGER;
  294.     
  295. BEGIN
  296.  
  297.     { Calculate space between edges of blitRect and edges of the bitmap. }
  298.      
  299.     myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  300.     MoveHHi(Handle(myOffScrHandle));
  301.     HLock(Handle(myOffScrHandle));
  302.     WITH myOffScrHandle^^ DO
  303.     BEGIN
  304.         leftSpace := gPort^.portBits.bounds.left - blitRect.left;
  305.         topSpace := gPort^.portBits.bounds.top - blitRect.top;
  306.         rightSpace := gPort^.portBits.bounds.right - blitRect.right;
  307.         bottomSpace := gPort^.portBits.bounds.bottom - blitRect.bottom;
  308.     END;
  309.     
  310.     { Then move blitRect, but not past the edge of the bitmap. }
  311.     
  312.     IF (dv = 0) THEN
  313.         IF (dh > 0) THEN {moving to the right}
  314.             IF (rightSpace > dh) THEN
  315.                 OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
  316.             ELSE
  317.             BEGIN
  318.                 dh := rightSpace;
  319.                 OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
  320.             END
  321.         ELSE {moving to the left}
  322.             IF (leftSpace > dh) THEN
  323.             BEGIN
  324.                 dh := leftSpace;
  325.                 OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
  326.             END
  327.             ELSE
  328.                 OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
  329.     ELSE IF (dv > 0) THEN {moving down}
  330.         IF (bottomSpace > dv) THEN
  331.             OffsetRect(myOffScrHandle^^.blitRect,dh,dv)
  332.         ELSE
  333.         BEGIN
  334.             dv := bottomSpace;
  335.             OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
  336.         END
  337.         ELSE IF (topSpace > dv) THEN {moving up}
  338.         BEGIN
  339.             dv := topSpace;
  340.             OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
  341.         END
  342.         ELSE
  343.             OffsetRect(myOffScrHandle^^.blitRect,dh,dv);
  344.                 
  345.     {Save actual distances moved to data structure.}
  346.     
  347.     WITH myOffScrHandle^^ DO
  348.     BEGIN
  349.         dhGraf := dhGraf + dh;
  350.         dvGraf := dvGraf + dv;
  351.     END;
  352.     HUnlock(Handle(myOffScrHandle));
  353.     
  354.     {Shoot new contents of blit rectangle to screen.}
  355.     
  356.     DrawContents(theWindow);
  357. END; {ScrollContents}
  358.     
  359.     
  360. PROCEDURE MyScroll(theControl:ControlHandle;partCode:INTEGER);
  361.     
  362. VAR
  363.     myOffScrHandle:                OffScrHandle;
  364.     myScrollHandle:                ScrollHandle;
  365.     dh,dv:                        LONGINT;
  366.     windowFull:                    LONGINT;
  367.     myCtlValue:                    LONGINT;
  368.     visHeight,visWidth:            LONGINT;
  369.     dontCare:                    LONGINT;
  370.     tempDH,tempDV:                LONGINT;
  371.     startValue:                    INTEGER;
  372.     myDocWidth,myDocHeight:        INTEGER;
  373.     direction:                    Str255;
  374.     theWindow:                    WindowPtr;
  375.     
  376. BEGIN
  377.     theWindow := theControl^^.contrlOwner;
  378.     myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  379.     MoveHHi(Handle(myOffScrHandle));
  380.     HLock(Handle(myOffScrHandle));
  381.     
  382.     {Make local copies of data structure items.}
  383.     
  384.     WITH myOffScrHandle^^ DO
  385.     BEGIN
  386.         tempDH := dhGraf;
  387.         tempDV := dvGraf;
  388.         myDocWidth := docWidth;
  389.         myDocHeight := docHeight;
  390.     END;
  391.     HUnlock(Handle(myOffScrHandle));
  392.     
  393.     {Initialize more variables for our formulas.}
  394.     
  395.     visHeight := theWindow^.portRect.bottom - 15 - theWindow^.portRect.top;
  396.     visWidth := theWindow^.portRect.right - 15 - theWindow^.portRect.left;
  397.     startValue := GetCtlValue(theControl);
  398.     GetCTitle(theControl,direction);
  399.     myScrollHandle := ScrollHandle(GetCRefCon(theControl));
  400.     MoveHHi(Handle(myScrollHandle));
  401.     HLock(Handle(myScrollHandle));
  402.     
  403.     {Implementation of two-speed, accelerating scroll bars.}
  404.     
  405.     WITH myScrollHandle^^ DO
  406.     BEGIN
  407.         heldDown := heldDown + 1;
  408.         IF (heldDown > 2) THEN
  409.             goFast := TRUE;
  410.     END; {WITH}
  411.  
  412.     CASE partCode OF
  413.         inUpButton:
  414.         BEGIN
  415.         
  416.             {Don't scroll up if already at top!}
  417.             
  418.             IF (startValue > 0) THEN
  419.             BEGIN
  420.                 IF (direction = 'MyVert') THEN
  421.                 BEGIN
  422.                     IF (visHeight >= myDocHeight) THEN
  423.                     BEGIN
  424.                         setCtlValue(theControl,0);
  425.                         ScrollContents(theWindow,0,-tempDV);
  426.                     END
  427.                     ELSE
  428.                     BEGIN
  429.                     
  430.                         {Scroll up five pixels}
  431.                         
  432.                         dv := tempDV - 5;
  433.                         
  434.                         {Set new thumb value using Golden Ratio.}
  435.                         
  436.                         myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
  437.                         ClipRect(theWindow^.portRect);
  438.                         setCtlValue(theControl,INTEGER(myCtlValue));
  439.                         
  440.                         {Update blit rectangle, blast document to screen.}
  441.                         
  442.                         ScrollContents(theWindow,0,-5);
  443.                     END; {IF visHeight...ELSE}
  444.                 END
  445.                 ELSE
  446.                 BEGIN
  447.                 
  448.                     {Repeat for horizontal direction.}
  449.                     
  450.                     IF (visWidth >= myDocWidth) THEN
  451.                     BEGIN
  452.                         setCtlValue(theControl,0);
  453.                         ScrollContents(theWindow,-tempDH,0);
  454.                     END
  455.                     ELSE
  456.                     BEGIN
  457.                         dh := tempDH - 5; 
  458.                         myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
  459.                         ClipRect(theWindow^.portRect);
  460.                         setCtlValue(theControl,INTEGER(myCtlValue));
  461.                         ScrollContents(theWindow,-5,0);
  462.                     END; {IF visWidth...ELSE}
  463.                 END; {IF direction...ELSE}
  464.             END; {IF startValue}
  465.             IF (myScrollHandle^^.goFast = FALSE) THEN
  466.                 Delay(10,dontCare);
  467.         END; {inUpButton}
  468.  
  469.         {Pattern is identical for down button, page up, and page down regions.}
  470.         
  471.         inDownButton:
  472.         BEGIN
  473.             IF (direction = 'MyVert') THEN
  474.             BEGIN
  475.                 IF (startValue < myDocHeight) THEN
  476.                 BEGIN
  477.                     dv := tempDV + 5; 
  478.                     myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
  479.                     ClipRect(theWindow^.portRect);
  480.                     setCtlValue(theControl,INTEGER(myCtlValue));
  481.                     ScrollContents(theWindow,0,5);
  482.                 END; {IF startValue}
  483.             END
  484.             ELSE
  485.             BEGIN
  486.                 IF (startValue < myDocWidth) THEN
  487.                 BEGIN
  488.                     dh := tempDH + 5; 
  489.                     myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
  490.                     ClipRect(theWindow^.portRect);
  491.                     setCtlValue(theControl,INTEGER(myCtlValue));
  492.                     ScrollContents(theWindow,5,0);
  493.                 END; {IF startValue}
  494.             END; {IF direction... ELSE}
  495.             IF (myScrollHandle^^.goFast = FALSE) THEN
  496.                 Delay(10,dontCare);
  497.         END; {inDownButton}
  498.             
  499.         inPageUp:
  500.         BEGIN
  501.             IF (startValue > 0) THEN
  502.             BEGIN
  503.                 IF (direction = 'MyVert') THEN
  504.                 BEGIN
  505.                     IF (visHeight >= myDocHeight) THEN
  506.                     BEGIN
  507.                         setCtlValue(theControl,0);
  508.                         ScrollContents(theWindow,0,-tempDV);
  509.                     END
  510.                     ELSE
  511.                     BEGIN
  512.                         windowFull := visHeight - 5;
  513.                         dv := tempDV - windowFull;
  514.                         IF (dv < 0) THEN
  515.                             dv := 0;
  516.                         myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
  517.                         ClipRect(theWindow^.portRect);
  518.                         setCtlValue(theControl,INTEGER(myCtlValue));
  519.                         ScrollContents(theWindow,0,-windowFull);
  520.                     END; {IF visHeight...ELSE}
  521.                 END {IF direction}
  522.                 ELSE
  523.                 BEGIN
  524.                     IF (visWidth >= myDocWidth) THEN
  525.                     BEGIN
  526.                         setCtlValue(theControl,0);
  527.                         ScrollContents(theWindow,-tempDH,0);
  528.                     END
  529.                     ELSE
  530.                     BEGIN
  531.                         windowFull := visWidth - 5;
  532.                         dh := tempDH - windowFull;
  533.                         IF (dh < 0) THEN
  534.                             dh := 0;
  535.                         myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
  536.                         ClipRect(theWindow^.portRect);
  537.                         setCtlValue(theControl,INTEGER(myCtlValue));
  538.                         ScrollContents(theWindow,-windowFull,0);
  539.                     END; {IF visWidth...ELSE}
  540.                 END; {IF direction... ELSE}
  541.                 IF (myScrollHandle^^.goFast = FALSE) THEN
  542.                     Delay(10,dontCare);
  543.             END; {IF startValue}
  544.         END; {inPageUp}
  545.             
  546.         inPageDown:
  547.         BEGIN
  548.             IF (direction = 'MyVert') THEN
  549.             BEGIN
  550.                 IF (startValue < myDocHeight) THEN
  551.                 BEGIN
  552.                     windowFull := visHeight - 5;
  553.                     dv := tempDV + windowFull;
  554.                     myCtlValue := LONGINT((dv * myDocHeight) DIV (myDocHeight - visHeight));
  555.                     ClipRect(theWindow^.portRect);
  556.                     setCtlValue(theControl,INTEGER(myCtlValue));
  557.                     ScrollContents(theWindow,0,windowFull);
  558.                 END; {IF startValue}
  559.             END {IF direction}
  560.             ELSE
  561.             BEGIN
  562.                 IF (startValue < myDocWidth) THEN
  563.                 BEGIN
  564.                     windowFull := visWidth - 5;
  565.                     dh := tempDH + windowFull;
  566.                     myCtlValue := LONGINT((dh * myDocWidth) DIV (myDocWidth - visWidth));
  567.                     ClipRect(theWindow^.portRect);
  568.                     setCtlValue(theControl,INTEGER(myCtlValue));
  569.                     ScrollContents(theWindow,windowFull,0);
  570.                 END; {IF startValue}
  571.             END; {IF direction... ELSE}
  572.             IF (myScrollHandle^^.goFast = FALSE) THEN
  573.                 Delay(10,dontCare);
  574.         END; {inPageDown}
  575.     END; {CASE partCode}
  576.     HUnlock(Handle(myScrollHandle));
  577.     ClipRect(theWindow^.portRect);  {so TrackControl can unhilite arrows when mouse is released}
  578. END; {MyScroll}
  579.     
  580.  
  581. PROCEDURE Window(paramPtr:XCmdPtr);
  582.     
  583. CONST
  584.     minParamCount        =    5;
  585.     smallestHeight        =    100;
  586.     smallestWidth        =    100;
  587.     _WaitNextEvent        =    $A860;
  588.     _Unimplemented        =    $A89F;
  589.     active                =    0;
  590.     inactive            =    255;
  591.     MouseMovedEvt        =    $FA;
  592.     SuspendResumeEvt    =    $01;
  593.     SuspendEventMask    =    $1;
  594.     ConvertScrapMask    =    $2;
  595.     browseTool            =    6069;
  596.     HCWidth                =    512;
  597.     HCHeight            =    342;
  598.     padding                =    16;
  599.             
  600. VAR
  601.     toolVis,patVis:                BOOLEAN;
  602.     msgVis,fatVis:                BOOLEAN;
  603.     hasWaitNextEvent:            BOOLEAN;
  604.     inBackGround,smallScreen:    BOOLEAN;
  605.     DoneFlag,HaveEvent:            BOOLEAN;
  606.     menuWasHidden:                BOOLEAN;
  607.     wTop,wLeft,wBottom,wRight:    INTEGER;
  608.     partCode,controlCode:        INTEGER;
  609.     largestHeight,largestWidth:    INTEGER;
  610.     dummy,charCode:                INTEGER;
  611.     screenWidth,screenHeight:    INTEGER;
  612.     myDocWidth,myDocHeight:        INTEGER;
  613.     eventPoint:                    Point;
  614.     wRect,screenRect,dragRect:    Rect;
  615.     winSizeLimits:                Rect;
  616.     oldSize:                    Rect;
  617.     newSize,dontCare:            LONGINT;
  618.     envError:                    OSErr;
  619.     cursorRgn:                    RgnHandle;
  620.     hScroll,vScroll:            ControlHandle;
  621.     whichControl:                ControlHandle;
  622.     myWindow,whichWindow:        WindowPtr;
  623.     fatBitsWindow:                WindowPtr;
  624.     HCrefresh:                    Str31;
  625.     wT,wL,wB,wR,wTitle:            Str255;
  626.     toolStr,patStr,msgStr:        Str255;
  627.     widthStr,heightStr:            Str255;
  628.     myBits:                        BitMap;
  629.     theEnv:                        SysEnvRec;
  630.     myEvent:                    EventRecord;
  631.     wRecord:                    WindowRecord;
  632.     HCPort:                        GrafPtr;
  633.     theOffScrHandle:            OffScrHandle;
  634.     theScrollHandle:            ScrollHandle;
  635.     myOffScr:                    OffScrRecord;
  636.     myScrollRecord:                ScrollRecord;
  637.         
  638.     
  639.     FUNCTION TrapAvailable(tNumber: INTEGER; tType: TrapType):BOOLEAN;
  640.  
  641.     {Check to see if a given trap is implemented.}
  642.  
  643.     BEGIN
  644.         TrapAvailable := NGetTrapAddress(tNumber, tType) <> GetTrapAddress(_Unimplemented);
  645.     END; {TrapAvailable}
  646.  
  647.  
  648.     FUNCTION CreateHScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
  649.     VAR
  650.         myWindowRect,hScrRect : Rect;
  651.         
  652.     BEGIN
  653.         SetPort(theWindow);
  654.         myWindowRect := theWindow^.portRect;
  655.         SetRect(hScrRect,myWindowRect.left -1,
  656.                          myWindowRect.bottom - 15,
  657.                          myWindowRect.right - 14,
  658.                          myWindowRect.bottom + 1);
  659.         CreateHScrollBar := NewControl(theWindow,hScrRect,'MyHoriz',TRUE,
  660.                                         theValue,theMin,theMax,scrollBarProc,theRefCon);
  661.     END; {CreateHScrollBar}
  662.     
  663.         
  664.     FUNCTION CreateVScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
  665.     VAR
  666.         myWindowRect,hScrRect : Rect;
  667.         
  668.     BEGIN
  669.         SetPort(theWindow);
  670.         myWindowRect := theWindow^.portRect;
  671.         SetRect(hScrRect,myWindowRect.right -15,
  672.                          myWindowRect.top - 1,
  673.                          myWindowRect.right + 1,
  674.                          myWindowRect.bottom - 14);
  675.         CreateVScrollBar := NewControl(theWindow,hScrRect,'MyVert',TRUE,
  676.                                         theValue,theMin,theMax,scrollBarProc,theRefCon);
  677.     END; {CreateVScrollBar}
  678.     
  679.     
  680.     PROCEDURE InvalScroll(theWindow:WindowPtr);
  681.     VAR
  682.         theRect,tallRect,wideRect : Rect;
  683.         
  684.     BEGIN
  685.         SetPort(theWindow);
  686.         theRect := theWindow^.portRect;
  687.         ClipRect(theRect);
  688.         
  689.         { Accumulate tallRect, which is occupied by the vertical scroll bar }
  690.         
  691.         SetRect(tallRect,theRect.right-15,
  692.                          theRect.top,
  693.                          theRect.right,
  694.                          theRect.bottom);
  695.         EraseRect(tallRect);
  696.         InvalRect(tallRect);
  697.         
  698.         { Accumulate wideRect, which is occupied by the horizontal scroll bar }
  699.         
  700.         SetRect(wideRect,theRect.left,
  701.                          theRect.bottom-15,
  702.                          theRect.right,
  703.                          theRect.bottom);
  704.         EraseRect(wideRect);
  705.         InvalRect(wideRect);
  706.     END; {InvalScroll}
  707.     
  708.     
  709.     PROCEDURE Deactivate(theWindow:WindowPtr);
  710.     
  711.     {Deactivate the scroll bars in theWindow in accordance
  712.      with the human interface guidelines. This means we must
  713.      erase everything enclosed by the control rectangles.}
  714.     
  715.     VAR
  716.         theControl:            ControlHandle;
  717.         theControlRect:        Rect;
  718.     
  719.     BEGIN
  720.     
  721.         {I always title my scroll bars 'MyVert' and 'MyHoriz'
  722.          so I can easily find them by walking the window's
  723.          control list.}
  724.          
  725.         theControl := WindowPeek(theWindow)^.controlList;
  726.         WHILE (theControl <> NIL) DO
  727.         BEGIN
  728.             IF (theControl^^.contrlTitle = 'MyVert') OR 
  729.                (theControl^^.contrlTitle = 'MyHoriz') THEN
  730.             BEGIN
  731.                 theControlRect := theControl^^.contrlRect;
  732.                 InsetRect(theControlRect,1,1);
  733.                 EraseRect(theControlRect);
  734.             END; {IF}
  735.             theControl := theControl^^.nextControl;
  736.         END; {WHILE}
  737.     END; {Deactivate}
  738.                 
  739.     
  740.     PROCEDURE HiliteScrollBars(theWindow:WindowPtr);
  741.     
  742.     VAR
  743.         myWindowRect:                Rect;
  744.         visWidth,visHeight:        INTEGER;
  745.         myDocWidth,myDocHeight:        INTEGER;
  746.         myCtlValue:                    INTEGER;
  747.         tempDH,tempDV:                LONGINT;
  748.         myOffScrHandle:                OffScrHandle;
  749.     
  750.     BEGIN
  751.         myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  752.         MoveHHi(Handle(myOffScrHandle));
  753.         HLock(Handle(myOffScrHandle));
  754.         
  755.         {Make local copies of data structure items.}
  756.         
  757.         WITH myOffScrHandle^^ DO
  758.         BEGIN
  759.             tempDH := dhGraf;
  760.             tempDV := dvGraf;
  761.             myDocWidth := docWidth;
  762.             myDocHeight := docHeight;
  763.         END;
  764.         
  765.         HUnlock(Handle(myOffScrHandle));
  766.         myWindowRect := theWindow^.portRect;
  767.         visHeight := myWindowRect.bottom - 15 - myWindowRect.top;
  768.         visWidth := myWindowRect.right - 15 - myWindowRect.left;
  769.         SetPort(theWindow);
  770.         ClipRect(myWindowRect);
  771.         
  772.         { Check to see if window is taller than contents. If
  773.           so, unhilite vertical scroll bar. Otherwise, use
  774.           Golden Ratio to draw vertical scroll bar with thumb 
  775.           in right position. }
  776.  
  777.         IF ((visHeight >= myDocHeight) AND (tempDV = 0)) THEN
  778.             HiliteControl(vScroll,INTEGER(inactive))
  779.         ELSE
  780.         BEGIN
  781.             HiliteControl(vScroll,INTEGER(active));
  782.             IF (visHeight >= myDocHeight) THEN
  783.                 SetCtlValue(vScroll,myDocHeight)
  784.             ELSE
  785.             BEGIN
  786.                 myCtlValue := LONGINT((tempDV * myDocHeight) DIV (myDocHeight - visHeight));
  787.                 ClipRect(theWindow^.portRect);
  788.                 setCtlValue(vScroll,INTEGER(myCtlValue));
  789.             END; {IF visHeight...ELSE}
  790.         END;
  791.             
  792.         { Repeat for horizontal scroll bar. }
  793.         
  794.         IF ((visWidth >= myDocWidth) AND (tempDH = 0)) THEN
  795.             HiliteControl(hScroll,INTEGER(inactive))
  796.         ELSE
  797.         BEGIN
  798.             HiliteControl(hScroll,INTEGER(active));
  799.             IF (visWidth >= myDocWidth) THEN
  800.                 SetCtlValue(hScroll,myDocWidth)
  801.             ELSE
  802.             BEGIN
  803.                 myCtlValue := LONGINT((tempDH * myDocWidth) DIV (myDocWidth - visWidth));
  804.                 ClipRect(theWindow^.portRect);
  805.                 setCtlValue(hScroll,INTEGER(myCtlValue));
  806.             END; {IF visWidth...ELSE}
  807.         END;
  808.             
  809.     END; {HiliteScrollBars}
  810.  
  811.  
  812.     PROCEDURE MoveScrollBars(theWindow:WindowPtr);
  813.     
  814.     VAR
  815.         myWindowRect:            Rect;
  816.         vScrRect,hScrRect:        Rect;
  817.  
  818.     BEGIN
  819.         myWindowRect := theWindow^.portRect;
  820.         SetRect(hScrRect,myWindowRect.left - 1,
  821.                          myWindowRect.bottom - 15,
  822.                          myWindowRect.right - 14,
  823.                          myWindowRect.bottom + 1);
  824.         SetRect(vScrRect,myWindowRect.right - 15,
  825.                          myWindowRect.top - 1,
  826.                          myWindowRect.right + 1,
  827.                          myWindowRect.bottom - 14);
  828.         SetPort(theWindow);
  829.         ClipRect(myWindowRect);
  830.         
  831.         { Hide and resize the scroll bars to fit the new window size. }
  832.             
  833.         HideControl(hScroll);
  834.         HideControl(vScroll);
  835.         MoveControl(hScroll,hScrRect.left,hScrRect.top);
  836.         SizeControl(hScroll,(hScrRect.right - hScrRect.left),
  837.                             (hScrRect.bottom - hScrRect.top));
  838.         MoveControl(vScroll,vScrRect.left,vScrRect.top);
  839.         SizeControl(vScroll,(vScrRect.right - vScrRect.left),
  840.                             (vScrRect.bottom - vScrRect.top));
  841.         HiliteScrollBars(theWindow);
  842.         ShowControl(hScroll);
  843.         ShowControl(vScroll);
  844.     END; {MoveScrollBars}
  845.     
  846.     
  847.     PROCEDURE ScrollWithThumb(theControl:ControlHandle;theEventPoint:Point);
  848.  
  849.     VAR
  850.         theWindow:                    WindowPtr;
  851.         myOffScrHandle:                OffScrHandle;
  852.         visWidth,visHeight:            INTEGER;
  853.         myDocWidth,myDocHeight:        INTEGER;
  854.         startValue,endValue:        INTEGER;
  855.         dummy:                        INTEGER;
  856.         amountToScroll:                LONGINT;
  857.         tempDH,tempDV:                LONGINT;
  858.         direction:                    Str255;
  859.  
  860.     BEGIN
  861.         theWindow := theControl^^.contrlOwner;
  862.         myOffScrHandle := OffScrHandle(GetWRefCon(theWindow));
  863.         MoveHHi(Handle(myOffScrHandle));
  864.         HLock(Handle(myOffScrHandle));
  865.         
  866.         {Make local copies of data structure items.}
  867.         
  868.         WITH myOffScrHandle^^ DO
  869.         BEGIN
  870.             tempDH := dhGraf;
  871.             tempDV := dvGraf;
  872.             myDocWidth := docWidth;
  873.             myDocHeight := docHeight;
  874.         END;
  875.         HUnlock(Handle(myOffScrHandle));
  876.         GetCTitle(theControl,direction);
  877.         visHeight := theWindow^.portRect.bottom -
  878.                        theWindow^.portRect.top - 15;
  879.         visWidth := theWindow^.portRect.right -
  880.                       theWindow^.portRect.left - 15;
  881.                       
  882.         {Record where thumb is before it is moved.}
  883.         
  884.         startValue := GetCtlValue(theControl);
  885.         
  886.         {Move it.}
  887.         
  888.         dummy := TrackControl(theControl,theEventPoint,NIL);
  889.         
  890.         {Record where thumb is released.}
  891.         
  892.         endValue := GetCtlValue(theControl);
  893.         
  894.         {Record the distance thumb was moved.}
  895.         
  896.         amountToScroll := LONGINT(endValue - startValue);
  897.         IF (direction = 'MyVert') THEN
  898.         BEGIN    {moved vertical scroll bar}
  899.             IF (endValue = 0) THEN    {moved thumb to top}
  900.                 ScrollContents(theWindow,0,-tempDV)
  901.             ELSE
  902.             IF (endValue = myDocHeight) THEN    {moved thumb to bottom}
  903.                 ScrollContents(theWindow,0,myDocHeight - tempDV)
  904.             ELSE
  905.             BEGIN
  906.                 {moved thumb somewhere in middle - use Golden Ratio to
  907.                  translate thumb movement into document movement.}
  908.                 amountToScroll := LONGINT((amountToScroll * 
  909.                                          (myDocHeight - visHeight)) DIV
  910.                                           myDocHeight);
  911.                 IF (ABS(amountToScroll) < 1) THEN
  912.                     {didn't move thumb far enough to scroll - snap it
  913.                      back to starting position.}
  914.                     SetCtlValue(theControl,startValue)
  915.                 ELSE
  916.                     ScrollContents(theWindow,0,INTEGER(amountToScroll));
  917.             END;
  918.         END
  919.         ELSE    {moved horizontal scroll bar}
  920.         BEGIN
  921.             IF (endValue = 0) THEN
  922.                 ScrollContents(theWindow,-tempDH,0)
  923.             ELSE
  924.             IF (endValue = myDocWidth) THEN
  925.                 ScrollContents(theWindow,myDocWidth - tempDH,0)
  926.             ELSE
  927.             BEGIN
  928.                 amountToScroll := LONGINT((amountToScroll * 
  929.                                          (myDocWidth - visWidth)) DIV
  930.                                           myDocWidth);
  931.                 IF (ABS(amountToScroll) < 1) THEN
  932.                     SetCtlValue(theControl,startValue)
  933.                 ELSE
  934.                     ScrollContents(theWindow,INTEGER(amountToScroll),0);
  935.             END;
  936.         END;
  937.     END; {ScrollWithThumb}
  938.         
  939.         
  940.     FUNCTION WhichDevice(thePoint:Point):GDHandle;
  941.     
  942.     VAR
  943.         aDevice:    GDHandle;
  944.         foundOne:    BOOLEAN;
  945.     
  946.     BEGIN
  947.         aDevice := GetDeviceList;
  948.         foundOne :=    FALSE;
  949.         
  950.         WHILE (aDevice <> NIL) AND NOT foundOne DO
  951.         BEGIN
  952.             IF PtInRect(thePoint,aDevice^^.gdRect) THEN
  953.             BEGIN
  954.                 WhichDevice := aDevice;
  955.                 foundOne := TRUE;
  956.             END;
  957.             aDevice := aDevice^^.gdNextGD;
  958.         END;
  959.     END;    { WhichDevice }
  960.     
  961.     
  962.     FUNCTION MenuBarHeight: INTEGER;
  963.     
  964.     {Returns the height of the menubar in pixels, as
  965.      read from the low memory global mBarHeight.}
  966.     
  967.     CONST
  968.         mBarHeight    =    $BAA;
  969.         
  970.     VAR
  971.         menuBarHeightPtr:    ^INTEGER;
  972.         
  973.     BEGIN
  974.         menuBarHeightPtr := Pointer(mBarHeight);
  975.         MenuBarHeight := menuBarHeightPtr^;
  976.     END; {MenuBarHeight}
  977.     
  978.     
  979.     FUNCTION OnAScreen(theRect:Rect):BOOLEAN;
  980.     
  981.     CONST
  982.         titleBarHeight    =    18;
  983.         
  984.     VAR
  985.         deskRgn:            RgnHandle;
  986.         topLeft,topRight:    Point;
  987.  
  988.     BEGIN
  989.         deskRgn := GetGrayRgn;
  990.         topLeft.v := theRect.top - titleBarHeight;
  991.         topLeft.h := theRect.left + titleBarHeight;
  992.         topRight.v := topLeft.v;
  993.         topRight.h := theRect.right - titleBarHeight;
  994.         IF ((PtInRgn(topLeft,deskRgn)) OR (PtInRgn(topRight,deskRgn))) THEN
  995.             OnAScreen := TRUE
  996.         ELSE
  997.             OnAScreen := FALSE;
  998.     END; {OnAScreen}
  999.  
  1000.  
  1001.     PROCEDURE ZoomIt(theWindow:WindowPtr;partCode:INTEGER;clickedWhere:Point);
  1002.     
  1003.     CONST
  1004.         titleBarHeight    =    18;
  1005.         
  1006.     TYPE
  1007.         WStatePtr        =    ^WStateData;
  1008.         WStateHandle    =    ^WStatePtr;
  1009.         
  1010.     VAR
  1011.         oldRect,newRect:    Rect;
  1012.         maxHeight:            INTEGER;
  1013.         
  1014.     BEGIN
  1015.         oldRect := theWindow^.portRect;
  1016.         IF theEnv.hasColorQD THEN
  1017.         BEGIN
  1018.             newRect := WhichDevice(clickedWhere)^^.gdRect;
  1019.             IF WhichDevice(clickedWhere) = GetMainDevice THEN
  1020.             BEGIN
  1021.                 newRect.top := newRect.top + MenuBarHeight;
  1022.             END;
  1023.         END
  1024.         ELSE
  1025.             newRect := GetGrayRgn^^.rgnBBox;
  1026.         newRect.left := newRect.left + 2;
  1027.         newRect.top := newRect.top + titleBarHeight + 2;
  1028.         newRect.right := newRect.right - 3;
  1029.         newRect.bottom := newRect.bottom - 3;
  1030.         IF NOT EqualRect(oldRect,newRect) THEN
  1031.             WITH WindowPeek(theWindow)^ DO
  1032.                 WStateHandle(dataHandle)^^.stdState := newRect;
  1033.         SetPort(theWindow);
  1034.         EraseRect(whichWindow^.portRect);        
  1035.         InvalRect(whichWindow^.portRect);
  1036.         ZoomWindow(theWindow,partcode,FALSE);
  1037.     END;    { ZoomIt }
  1038.             
  1039.             
  1040.     {$I XCmdGlue.inc}
  1041.     
  1042.     
  1043.     PROCEDURE Fail(errStr:Str255);
  1044.  
  1045.     {Fail returns errStr to HyperCard and exits the XCMD.
  1046.      errStr can then be checked by inspecting HyperCard's
  1047.      global variable "the result." See "XCMD's for Hyper-
  1048.      Card" by Gary Bond (MIS Press, 1988) for more details.
  1049.  
  1050.      © 1988 by Gary Bond
  1051.      All rights reserved.
  1052.      You may use this code for NON-COMMERCIAL purposes.}
  1053.  
  1054.     BEGIN
  1055.         paramPtr^.returnValue := PasToZero(errStr);
  1056.         SysBeep(1);
  1057.         EXIT(Window);
  1058.     END; {Fail}
  1059.     
  1060.     
  1061.     PROCEDURE CheckParamCount;
  1062.  
  1063.     {CheckParamCount sees if the number of parameters
  1064.      passed to the XCMD matches the number expected. If
  1065.      not, we exit from the XCMD with an error message.
  1066.      See "XCMD's for HyperCard" by Gary Bond (MIS Press,
  1067.      1988) for more details.
  1068.  
  1069.      © 1988 by Gary Bond
  1070.      All rights reserved.
  1071.      You may use this code for NON-COMMERCIAL purposes.}
  1072.  
  1073.     VAR
  1074.         numParams : INTEGER;
  1075.         
  1076.     BEGIN
  1077.         numParams := paramPtr^.paramCount;
  1078.         IF(numParams <> minParamCount) THEN
  1079.             Fail('Form: HyperWindow "Window Title",top,left,bottom,right');
  1080.     END;    {CheckParamCount}
  1081.     
  1082.     
  1083.     FUNCTION GetHCVersion:Str255;
  1084.     
  1085.     {Return a string containing the version of HyperCard
  1086.      being used; e.g., '1.2'}
  1087.     
  1088.     BEGIN
  1089.         ZeroToPas(EvalExpr('the version')^,GetHCVersion);
  1090.     END;
  1091.     
  1092.     
  1093.     PROCEDURE HideWindoids;
  1094.  
  1095.     {Get and save the visible state of the tool, pattern,
  1096.      message and fatbits windoids; then hide them if they
  1097.      are showing.}
  1098.  
  1099.     VAR
  1100.         toolH,patH,msgH,fatH:    Handle;
  1101.         
  1102.         PROCEDURE HideFatBits;
  1103.  
  1104.         {HyperCard does not have a built-in command for hiding
  1105.          and showing the fatbits windoid, so we have to do it
  1106.          ourselves. HideFatBits walks the window list until it
  1107.          finds a window with title "FatBits," then hides it if
  1108.          the visible field of its WindowRecord is true. 
  1109.          HideFatBits also saves the WindowPtr to the fatbits
  1110.          windoid so we can use it later (e.g., to show the
  1111.          windoid again).}
  1112.  
  1113.         CONST
  1114.             windowList            =    $9D6; {Low memory global location.}
  1115.  
  1116.         VAR
  1117.             theWindow:        WindowPeek;
  1118.             theWindowPtr:    ^WindowPtr;
  1119.         
  1120.         BEGIN
  1121.             theWindowPtr := Pointer(windowList);
  1122.             theWindow := WindowPeek(theWindowPtr^);
  1123.             fatVis := FALSE;
  1124.             WHILE (theWindow <> NIL) DO
  1125.             BEGIN
  1126.                 IF (theWindow^.titleHandle^^ = 'FatBits') THEN
  1127.                 BEGIN
  1128.                     fatBitsWindow := WindowPtr(theWindow);
  1129.                     IF (theWindow^.visible = TRUE) THEN
  1130.                     BEGIN
  1131.                         fatVis := TRUE;
  1132.                         HideWindow(fatBitsWindow);
  1133.                         theWindow := NIL;
  1134.                     END;
  1135.                 END;
  1136.                 IF (theWindow <> NIL) THEN
  1137.                     theWindow := WindowPeek(theWindow)^.nextWindow;
  1138.             END; {WHILE}
  1139.         END; {HideFatBits}
  1140.         
  1141.     BEGIN {HideWindoids}
  1142.  
  1143.         {Get visible state of windoids.}
  1144.  
  1145.         toolH := EvalExpr('visible of tool window');
  1146.         ZeroToPas(toolH^,toolStr);
  1147.         DisposHandle(toolH);
  1148.         toolVis := StrToBool(toolStr);
  1149.  
  1150.         patH := EvalExpr('visible of pattern window');
  1151.         ZeroToPas(patH^,patStr);
  1152.         DisposHandle(patH);
  1153.         patVis := StrToBool(patStr);
  1154.  
  1155.         msgH := EvalExpr('visible of message window');
  1156.         ZeroToPas(msgH^,msgStr);
  1157.         DisposHandle(msgH);
  1158.         msgVis := StrToBool(msgStr);
  1159.         
  1160.         {Hide the ones that are showing.}
  1161.         
  1162.         HideFatBits;
  1163.         
  1164.         IF toolVis THEN
  1165.             SendHCMessage('hide tool window');
  1166.         IF patVis THEN
  1167.             SendHCMessage('hide pattern window');
  1168.         IF msgVis THEN
  1169.             SendHCMessage('hide message window');
  1170.     END;    {HideWindoids}
  1171.     
  1172.     
  1173.     PROCEDURE ShowWindoids;
  1174.  
  1175.     {This routine assumes HideWindoids has been called
  1176.      before. ShowWindoids restores the visible state of
  1177.      the windoids to that saved by HideWindoids.}
  1178.  
  1179.     BEGIN
  1180.         IF toolVis THEN
  1181.             SendHCMessage('show tool window');
  1182.         IF patVis THEN
  1183.             SendHCMessage('show pattern window');
  1184.         IF msgVis THEN
  1185.             SendHCMessage('show message window');
  1186.  
  1187.         {As in HideWindoids, we must take care of the FatBits
  1188.          windoid ourselves.}
  1189.  
  1190.         IF fatVis THEN
  1191.         BEGIN
  1192.             ShowWindow(fatBitsWindow);
  1193.             SelectWindow(fatBitsWindow);
  1194.         END;
  1195.     END;    {ShowWindoids}
  1196.     
  1197.     
  1198.     PROCEDURE ToggleMenuBar;
  1199.         
  1200.     {Set the visible of the menubar to not the visible of
  1201.      the menubar.}
  1202.         
  1203.     BEGIN
  1204.         IF MenuBarHeight = 0 THEN
  1205.             SendHCMessage('show menuBar')
  1206.         ELSE
  1207.             SendHCMessage('hide menuBar');
  1208.     END; {ToggleMenuBar}
  1209.         
  1210.     
  1211.     PROCEDURE GetHCBitMap;
  1212.     
  1213.     VAR
  1214.         myDocHeight,myDocWidth:    INTEGER;
  1215.         HCRect,myHCRect:        Rect;
  1216.         dummyGrafPtr:            GrafPtr;
  1217.         HCBits:                    BitMap;
  1218.         
  1219.     BEGIN
  1220.         MoveHHi(Handle(theOffScrHandle));
  1221.         HLock(Handle(theOffScrHandle));
  1222.         WITH theOffScrHandle^^ DO
  1223.         BEGIN
  1224.             myDocWidth := docWidth;
  1225.             myDocHeight := docHeight;
  1226.         END;
  1227.         myBits.rowBytes := (((myDocWidth - 1) DIV 16) + 1) * 2;
  1228.         myBits.baseAddr := NewPtr(myBits.rowBytes * myDocHeight);
  1229.         IF (myBits.baseAddr = NIL) THEN
  1230.             Fail('Could not allocate bitmap.');
  1231.         HCRect := HCPort^.portRect;
  1232.         HCBits := HCPort^.portBits;
  1233.         SetRect(myBits.bounds,0,
  1234.                                 0,
  1235.                               528,
  1236.                               358);
  1237.         
  1238.         dummyGrafPtr := GrafPtr(NewPtr(sizeOf(GrafPort)));
  1239.         IF (dummyGrafPtr = NIL) THEN
  1240.         BEGIN
  1241.             DisposPtr(myBits.baseAddr);
  1242.             Fail('Could not allocate offscreen grafPort.');
  1243.         END;
  1244.         theOffScrHandle^^.gPort := dummyGrafPtr;
  1245.         OpenPort(theOffScrHandle^^.gPort);
  1246.         SetOrigin(0,0);
  1247.         SetPortBits(myBits);
  1248.         MovePortTo(0,0);
  1249.         PortSize(myDocWidth,myDocHeight);
  1250.         RectRgn(theOffScrHandle^^.gPort^.visRgn,theOffScrHandle^^.gPort^.portRect);
  1251.         RectRgn(theOffScrHandle^^.gPort^.clipRgn,theOffScrHandle^^.gPort^.portRect);
  1252.         EraseRect(theOffScrHandle^^.gPort^.portRect);
  1253.         SetRect(myHCRect,0,
  1254.                          0,
  1255.                          512,
  1256.                          342);
  1257.         CopyBits(HCBits,theOffScrHandle^^.gPort^.portBits,HCRect,myHCRect,srcCopy,NIL);
  1258.         HUnlock(Handle(theOffScrHandle));
  1259.     END; {GetHCBitMap}
  1260.     
  1261.     
  1262.      PROCEDURE AdjustCursor;
  1263.     
  1264.     {AdjustCursor changes cursorRgn to the region that contains
  1265.      the cursor.  As soon as the cursor moves out of cursorRgn, we
  1266.      get an event and can change the cursor and cursorRgn again.
  1267.      cursorRgn is either the content region of our window or
  1268.      the region containing everything BUT the content region of our
  1269.      window.}
  1270.       
  1271.     VAR
  1272.         mousePt:        Point;
  1273.         myWinContRect:    Rect;
  1274.         myWinContRgn:    RgnHandle;
  1275.         deskRgn:        RgnHandle;
  1276.         handHdl:        CursHandle;
  1277.     
  1278.     BEGIN
  1279.         SetPort(myWindow);
  1280.         GetMouse(mousePt);
  1281.         LocalToGlobal(mousePt);
  1282.         myWinContRgn := NewRgn;
  1283.         
  1284.         {Calculate the "work region" of our window, which is its
  1285.          content region minus the scroll bars and grow icon. This
  1286.          is the region within which we want the cursor to change
  1287.          to a cross, and outside of which we want it to be an arrow.}
  1288.         
  1289.         WITH WindowPeek(myWindow)^.contRgn^^.rgnBBox DO
  1290.             SetRect(myWinContRect,left, top, right - 15, bottom - 15);
  1291.         RectRgn(myWinContRgn,myWinContRect);
  1292.                                 
  1293.         IF PtInRect(mousePt,myWinContRect) THEN
  1294.         BEGIN
  1295.         
  1296.             {The cursor is in the work region of our window}
  1297.             
  1298.             handHdl := GetCursor(browseTool);
  1299.             IF (handHdl <> NIL) THEN
  1300.                 SetCursor(handHdl^^)
  1301.             ELSE
  1302.                 InitCursor;
  1303.             
  1304.             {Set the cursor region equal to our window's work region.}
  1305.             
  1306.             SetEmptyRgn(cursorRgn);
  1307.             CopyRgn(myWinContRgn,cursorRgn);
  1308.         END
  1309.         ELSE
  1310.         BEGIN
  1311.         
  1312.             {The cursor is outside our window.}
  1313.             
  1314.             InitCursor;
  1315.             
  1316.             {Get the current desktop region}
  1317.             
  1318.             deskRgn := GetGrayRgn;
  1319.             
  1320.             {Set cursorRgn to the desktop region's bounding box.  It is
  1321.              important to add the menu bar area to cursorRgn too.}
  1322.              
  1323.             SetRectRgn(cursorRgn, deskRgn^^.rgnBBox.left,
  1324.                                   deskRgn^^.rgnBBox.top,
  1325.                                   deskRgn^^.rgnBBox.right,
  1326.                                   deskRgn^^.rgnBBox.bottom);
  1327.                                   
  1328.             {Punch out our window's content region from the big region}
  1329.             
  1330.             DiffRgn(cursorRgn,myWinContRgn,cursorRgn);
  1331.         END;
  1332.         DisposeRgn(myWinContRgn);
  1333.     END; {AdjustCursor}
  1334.  
  1335.  
  1336. BEGIN {Main Program}
  1337.  
  1338.     {Check the HyperCard version.  Must be 1.2 or greater.}
  1339.     
  1340.     IF GetHCVersion < '1.2' THEN
  1341.         Fail('Sorry, must have HyperCard 1.2 or greater.');
  1342.         
  1343.     {Save thy grafPort upon entering!}
  1344.     
  1345.     GetPort(HCPort);
  1346.     
  1347.     {Check and reset our environment.}
  1348.     
  1349.     CheckParamCount;
  1350.     FlushEvents(everyEvent,0);
  1351.     InitCursor;
  1352.     
  1353.     { Find out what kind of machine we're running on }
  1354.     
  1355.     envError := SysEnvirons(1,theEnv);
  1356.     IF (envError <> noErr) THEN
  1357.         Fail('SysEnvirons call failed.');
  1358.  
  1359.     { Convert HyperTalk input parameters for use here }
  1360.     
  1361.     ZeroToPas(paramPtr^.params[1]^,wTitle);
  1362.     ZeroToPas(paramPtr^.params[2]^,wT);
  1363.     ZeroToPas(paramPtr^.params[3]^,wL);
  1364.     ZeroToPas(paramPtr^.params[4]^,wB);
  1365.     ZeroToPas(paramPtr^.params[5]^,wR);
  1366.         
  1367.     wTop := INTEGER(StrToNum(wT));
  1368.     wLeft := INTEGER(StrToNum(wL));
  1369.     wBottom := INTEGER(StrToNum(wB));
  1370.     wRight := INTEGER(StrToNum(wR));
  1371.         
  1372.     {If window size parameters are too small or illegal, set
  1373.      the window to a predefined minimum size.}
  1374.  
  1375.     IF ((wRight - wLeft) < smallestWidth) THEN
  1376.         wRight := wLeft + smallestWidth;
  1377.     IF ((wBottom - wTop) < smallestHeight) THEN
  1378.         wBottom := wTop + smallestHeight;
  1379.         
  1380.     {Make sure the user is not trying to draw the window off
  1381.      the screen or under the menubar.}
  1382.  
  1383.     SetRect(wRect,wLeft,wTop,wRight,wBottom);
  1384.     IF NOT OnAScreen(wRect) THEN
  1385.         Fail('You are trying to draw your window off the screen!');
  1386.  
  1387.     {Get the bounds of the desktop.}
  1388.  
  1389.     screenRect := GetGrayRgn^^.rgnBBox;
  1390.     
  1391.     {If we have a small screen, make a note of it so we can hide the
  1392.      card window during context switches under MultiFinder.}
  1393.      
  1394.     ZeroToPas(EvalExpr('item 3 of the screenRect')^,widthStr);
  1395.     screenWidth := INTEGER(StrToNum(widthStr));
  1396.     ZeroToPas(EvalExpr('item 4 of the screenRect')^,heightStr);
  1397.     screenHeight := INTEGER(StrToNum(heightStr));
  1398.     
  1399.     IF (screenWidth = 512) AND (screenHeight = 342) THEN
  1400.            smallScreen := TRUE
  1401.     ELSE
  1402.         smallScreen := FALSE;
  1403.     
  1404.     HideWindoids;
  1405.     
  1406.     IF MenuBarHeight > 0 THEN
  1407.         menuWasHidden := FALSE
  1408.     ELSE
  1409.         menuWasHidden := TRUE;
  1410.     
  1411.     theOffScrHandle := OffScrHandle(NewHandle(SizeOf(OffScrRecord)));
  1412.     IF MemError <> noErr THEN
  1413.         Fail('Out of memory.  Buy more.');
  1414.         
  1415.     myDocWidth := HCWidth + padding;
  1416.     myDocHeight := HCHeight + padding;
  1417.     
  1418.     MoveHHi(Handle(theOffScrHandle));
  1419.     HLock(Handle(theOffScrHandle));
  1420.     WITH theOffScrHandle^^ DO
  1421.     BEGIN
  1422.         docWidth := myDocWidth;
  1423.         docHeight := myDocHeight;
  1424.     END;
  1425.     HUnlock(Handle(theOffScrHandle));
  1426.     
  1427.     GetHCBitMap;
  1428.     
  1429.     myWindow := NewWindow(@wRecord,wRect,wTitle,TRUE,zoomDocProc,
  1430.                           WindowPtr(-1),TRUE,1);
  1431.     IF (myWindow = NIL) THEN
  1432.     BEGIN
  1433.         DisposPtr(myBits.baseAddr);
  1434.         ClosePort(myOffScr.gPort);
  1435.         DisposPtr(Ptr(myOffScr.gPort));
  1436.         ShowWindoids;
  1437.         Fail('Not enough memory to draw window.');
  1438.     END
  1439.     ELSE
  1440.     BEGIN
  1441.         SetWRefCon(myWindow,LONGINT(theOffScrHandle));
  1442.         InitBlit(myWindow);
  1443.         DrawGrowIcon(myWindow);
  1444.         theScrollHandle := ScrollHandle(NewHandle(SizeOf(ScrollRecord)));
  1445.         IF MemError <> noErr THEN
  1446.             Fail('Out of memory.  Buy more.');
  1447.         theScrollHandle^^.heldDown := 0;
  1448.         theScrollHandle^^.goFast := FALSE;
  1449.  
  1450.         {Draw horizontal and vertical scroll bars in our 
  1451.          window.}
  1452.  
  1453.         hScroll := CreateHScrollBar(myWindow,0,0,myDocWidth,LONGINT(theScrollHandle));
  1454.         vScroll := CreateVScrollBar(myWindow,0,0,myDocHeight,LONGINT(theScrollHandle));
  1455.         HiliteScrollBars(myWindow);
  1456.         DrawContents(myWindow);
  1457.         SetRect(dragRect,screenRect.left + 4,
  1458.                          screenRect.top,
  1459.                          screenRect.right - 4,
  1460.                          screenRect.bottom - 4);
  1461.         largestHeight := screenRect.bottom - screenRect.top;
  1462.         largestWidth := screenRect.right - screenRect.left;
  1463.         SetRect(winSizeLimits,smallestWidth,
  1464.                               smallestHeight,
  1465.                               largestWidth,
  1466.                               largestHeight);
  1467.             
  1468.         HCRefresh := 'Go to this card';
  1469.         cursorRgn := NewRgn;
  1470.         inBackGround := FALSE;
  1471.         DoneFlag := FALSE;
  1472.         REPEAT
  1473.  
  1474.             {Call WaitNextEvent, if available. Otherwise call
  1475.              GetNextEvent.}
  1476.  
  1477.             IF hasWaitNextEvent THEN
  1478.                 HaveEvent := WaitNextEvent(everyEvent,myEvent,15,cursorRgn)
  1479.             ELSE
  1480.             BEGIN
  1481.                 HaveEvent := GetNextEvent(everyEvent,myEvent);
  1482.                 AdjustCursor;
  1483.             END;
  1484.             IF HaveEvent THEN
  1485.             BEGIN
  1486.                 IF (myEvent.what = app4Evt) THEN
  1487.  
  1488.                     {Pre-process app4Evt's fed to us by MultiFinder.}
  1489.  
  1490.                     CASE BSR(myEvent.message,24) OF
  1491.                     
  1492.                         MouseMovedEvt:
  1493.                             AdjustCursor;
  1494.                         
  1495.                         SuspendResumeEvt:
  1496.                         BEGIN
  1497.                             myEvent.what := activateEvt;
  1498.                                 
  1499.                             { Resume event }
  1500.                                 
  1501.                             IF (BAND(myEvent.message,SuspendEventMask) <> 0) THEN
  1502.                                 inBackground := FALSE
  1503.                             ELSE
  1504.                                 
  1505.                             { Suspend event }
  1506.                             
  1507.                                 inBackground := TRUE;
  1508.                                 
  1509.                             myEvent.message := LONGINT(myWindow);
  1510.                         END; {SuspendResumeEvt}
  1511.                             
  1512.                     END;    {CASE BSR}
  1513.             END;    {IF HaveEvent}
  1514.  
  1515.             CASE myEvent.what OF
  1516.                 
  1517.                 mouseDown:
  1518.                 BEGIN
  1519.                     partCode := FindWindow(myEvent.where,whichWindow);
  1520.                     IF (whichWindow = myWindow) THEN
  1521.                     BEGIN
  1522.  
  1523.                         {Deal with mouse hits to our window.}
  1524.  
  1525.                         CASE partCode OF
  1526.                             
  1527.                             inDrag:
  1528.                             BEGIN
  1529.                                 SelectWindow(whichWindow); {DragWindow bug}
  1530.                                 DragWindow(whichWindow,myEvent.where,dragRect);
  1531.                                 SendCardMessage(HCrefresh);
  1532.                                 AdjustCursor;
  1533.                             END;
  1534.  
  1535.                             inGrow:
  1536.                             BEGIN
  1537.                                 IF StillDown THEN    {GrowWindow bug}
  1538.                                 BEGIN
  1539.                                     oldSize := whichWindow^.portRect;
  1540.                                     newSize := GrowWindow(whichWindow,myEvent.where,winSizeLimits);
  1541.                                     IF (newSize <> 0) THEN
  1542.                                     BEGIN
  1543.                                         InvalScroll(whichWindow);
  1544.                                         SizeWindow(whichWindow,LOWORD(newSize),HIWORD(newSize),FALSE);
  1545.                                         InvalContents(whichWindow,oldSize);
  1546.                                         DrawGrowIcon(whichWindow);
  1547.                                         MoveScrollBars(whichWindow);
  1548.                                     END; {IF newSize}
  1549.                                 END; {IF StillDown}
  1550.                             END; {inGrow}
  1551.                                 
  1552.                             inZoomIn,inZoomOut:
  1553.                             BEGIN
  1554.                                 IF (TrackBox(whichWindow,myEvent.where,partCode)) THEN
  1555.                                 BEGIN
  1556.                                     InvalScroll(whichWindow);
  1557.                                     ZoomIt(whichWindow,partCode,myEvent.where);
  1558.                                     InvalContents(whichWindow,oldSize);
  1559.                                     DrawGrowIcon(whichWindow);
  1560.                                     MoveScrollBars(whichWindow);
  1561.                                 END;
  1562.                             END;
  1563.                                 
  1564.                             inContent:
  1565.                             BEGIN
  1566.                                 SetPort(whichWindow);
  1567.                                 eventPoint := myEvent.where;
  1568.                                 GlobalToLocal(eventPoint);
  1569.                                 controlCode := FindControl(eventPoint,whichWindow,whichControl);
  1570.                                 ClipRect(whichWindow^.portRect);
  1571.                                 IF (controlCode = inThumb) THEN
  1572.                                     ScrollWithThumb(whichControl,eventPoint)
  1573.                                 ELSE
  1574.                                 BEGIN
  1575.                                     IF (controlCode <> 0) THEN
  1576.                                     BEGIN
  1577.                                         WITH ScrollHandle(whichControl^^.contrlRfCon)^^ DO
  1578.                                         BEGIN
  1579.                                             heldDown := 0;
  1580.                                             goFast := FALSE;
  1581.                                         END;
  1582.                                         dummy := TrackControl(whichControl,eventPoint,@MyScroll);
  1583.                                     END; {IF controlCode}
  1584.                                 END; {IF controlCode}
  1585.                             END; {inContent}
  1586.                                     
  1587.                             inGoAway:
  1588.                             BEGIN
  1589.                                 IF(TrackGoAway(whichWindow,myEvent.where)) THEN
  1590.                                     DoneFlag := TRUE;
  1591.                             END;
  1592.                             
  1593.                         END; {CASE partCode}
  1594.                     END
  1595.                     ELSE
  1596.                     BEGIN
  1597.                         IF MenuBarHeight > 0 THEN
  1598.                         BEGIN
  1599.                             FlashMenuBar(0);
  1600.                             Delay(LONGINT(6),dontCare);
  1601.                             FlashMenuBar(0);
  1602.                         END; {IF MenuBarHeight}
  1603.                     END; {IF FindWindow...ELSE}
  1604.                 END; {mouseDown}
  1605.                     
  1606.                 activateEvt:
  1607.                 BEGIN
  1608.                     IF(WindowPtr(myEvent.message) = myWindow) THEN
  1609.                     BEGIN
  1610.                         SetPort(myWindow);
  1611.                         ClipRect(myWindow^.portRect);
  1612.                         DrawGrowIcon(myWindow);
  1613.                         IF inBackground THEN
  1614.                         BEGIN
  1615.  
  1616.                             {We've been sent behind another application
  1617.                              under MultiFinder, so deactivate the scroll
  1618.                              bars and show the menubar if it was hidden.}
  1619.  
  1620.                             Deactivate(myWindow);
  1621.                             IF smallScreen THEN
  1622.                                 ShowHide(WindowPtr(HCPort),FALSE);
  1623.                             IF MenuBarHeight = 0 THEN
  1624.                             BEGIN
  1625.                                 SendHCMessage('show menubar');
  1626.                                 menuWasHidden := TRUE;
  1627.                             END
  1628.                             ELSE
  1629.                                 menuWasHidden := FALSE;
  1630.                         END
  1631.                         ELSE
  1632.                         BEGIN
  1633.  
  1634.                             {We've been brought to the front under Multi-
  1635.                              Finder, so reactivate the scroll bars and
  1636.                              hide the menubar if it was hidden before.}
  1637.  
  1638.                             ShowHide(WindowPtr(HCPort),TRUE);
  1639.                             IF menuWasHidden THEN
  1640.                                 SendHCMessage('hide menubar');
  1641.                             DrawControls(myWindow);
  1642.                             HiliteScrollBars(myWindow);
  1643.                             FlushEvents(everyEvent,0);
  1644.                         END; {IF inBackground}
  1645.                     END; {IF WindowPtr}
  1646.                 END; {activateEvt}
  1647.                     
  1648.                 updateEvt:
  1649.                 BEGIN
  1650.                 
  1651.                     {Handle updates to our window.}
  1652.                     
  1653.                     IF(WindowPtr(myEvent.message) = myWindow) THEN
  1654.                     BEGIN
  1655.                     
  1656.                         {Always do this stuff}
  1657.                         
  1658.                         SetPort(myWindow);
  1659.                         BeginUpdate(myWindow);
  1660.                         ClipRect(myWindow^.portRect);
  1661.                         DrawGrowIcon(myWindow);
  1662.  
  1663.                         {Always do this stuff under single Finder but
  1664.                          only if in foreground under MultiFinder}
  1665.  
  1666.                         IF NOT inBackground THEN
  1667.                         BEGIN
  1668.                             HiliteScrollBars(myWindow);
  1669.                             DrawControls(myWindow);
  1670.                             AdjustCursor;
  1671.                         END;
  1672.                         
  1673.                         {Always do this stuff}
  1674.                         
  1675.                         DrawContents(myWindow);
  1676.                         EndUpdate(myWindow);
  1677.                     END {IF myEvent.message}
  1678.  
  1679.                     {Handle updates to HyperCard's card window.}
  1680.  
  1681.                     ELSE IF (WindowPtr(myEvent.message) = WindowPtr(HCPort)) THEN
  1682.                     BEGIN
  1683.                         SendHCMessage(HCRefresh);
  1684.  
  1685.                         {Must zero out card window's update region
  1686.                          ourselves because the SendHCMessage call
  1687.                          doesn't do it, and we'll wind up in an
  1688.                          infinite loop if we don't.}
  1689.  
  1690.                         BeginUpdate(WindowPtr(HCPort));
  1691.                         EndUpdate(WindowPtr(HCPort));
  1692.                     END; {IF... ELSE}
  1693.                 END; {updateEvt}
  1694.                     
  1695.                 keyDown:
  1696.                 BEGIN
  1697.                     IF(BitAnd(myEvent.modifiers,cmdKey) <> 0) THEN
  1698.                     BEGIN
  1699.                         charCode := BitAnd(myEvent.message,charCodeMask);
  1700.                         
  1701.                         {Pressing command-spacebar toggles the menubar.}
  1702.                         
  1703.                         IF(CHR(charCode) = ' ') THEN
  1704.                             ToggleMenuBar
  1705.  
  1706.                         {Pressing command-W closes the window and exits
  1707.                           the XCMD.}
  1708.  
  1709.                         ELSE IF(CHR(charCode) = 'w') THEN
  1710.                             DoneFlag := True;
  1711.                     END;
  1712.                 END;
  1713.             END; {CASE myEvent.what}
  1714.                 
  1715.         UNTIL (DoneFlag = True);
  1716.  
  1717.         {Clean up and get outta here!}
  1718.  
  1719.         DisposeRgn(cursorRgn);
  1720.         DisposPtr(myBits.baseAddr);
  1721.         ClosePort(theOffScrHandle^^.gPort);
  1722.         DisposPtr(Ptr(theOffScrHandle^^.gPort));
  1723.         DisposHandle(Handle(theOffScrHandle));
  1724.         DisposHandle(Handle(theScrollHandle));
  1725.         CloseWindow(myWindow);
  1726.         SendCardMessage(HCrefresh);
  1727.         ShowWindoids;
  1728.         InitCursor;
  1729.         FlushEvents(everyEvent,0);
  1730.         
  1731.         {Restore thy grafPort}
  1732.         
  1733.         SetPort(HCPort);
  1734.     END; {IF myWindow...ELSE}
  1735. END; {Main}
  1736. END. {Window}